import type { RouteRecordRaw } from 'vue-router'

function loadLocalRoutes() {
  // 1. 动态获取所有的路由对象，并放在数组中
  // * 路由对象都在对立的文件中
  // * 从文件中见所有路由对象先读取树中中
  const localRoutes: RouteRecordRaw[] = []
  // 1.1 读取router/main所有的ts文件 (webpack为require.context())
  // eager: true 立即加载，直接获取module，而不是获取import类型的key/value，中value为import对象类型
  const files: Record<string, any> = import.meta.glob('@/router/main/**/*.ts', { eager: true })
  for (const key in files) {
    const module = files[key]
    localRoutes.push(module.default)
  }

  return localRoutes
}

function addLocationRouter(userMenus: any[], localRoutes: RouteRecordRaw[], pMenu: any) {
  const routes: RouteRecordRaw[] = []
  let firstMenu: any = null
  function findLocationRouter(userMenus: any[], localRoutes: RouteRecordRaw[], pMenu: any) {
    for (const menu of userMenus) {
      if (menu.type != 2) {
        findLocationRouter(menu.children ?? [], localRoutes, menu)
      } else {
        const route = localRoutes.find((o) => o.path === menu.url)
        if (route) {
          // 给routes的顶层菜单添加重定向功能（但是只添加一层）
          if (!routes.find((o) => o.path === pMenu.url)) {
            routes.push({ path: pMenu.url, redirect: route.path })
          }
          // 将二级菜单加入到routes
          routes.push(route)
        }
        // 当firstMenu没有值的情况
        if (!firstMenu && route) firstMenu = menu
      }
    }
  }

  findLocationRouter(userMenus, localRoutes, pMenu)
  return {
    routes,
    firstMenu
  }
}

/**
 * @description 将当前用户路由与本地全部路由映射
 * @param userMenus 当前用户所拥有的路由
 * @returns 当前用户所拥有的菜单映射和当前用户第一个匹配的route组合的对象
 */
export function mapMenusToRoutes(userMenus: any[]) {
  const localRoutes = loadLocalRoutes()
  const { routes, firstMenu } = addLocationRouter(userMenus, localRoutes, {})
  return {
    routes,
    firstMenu
  }
}

/**
 * @description 根据路径匹配需要显示的菜单
 * @param path 匹配的路径
 * @param userMenus 当前用户所有的菜单
 * @returns route 当前匹配的菜单, 如果没有匹配到选中当前用户第一个菜单
 * */
export function mapPathToMenu(path: string, userMenus: any[]) {
  let { firstMenu } = mapMenusToRoutes(userMenus)
  // 递归不好返回值，因此需要在包裹一层
  function findPathToMenu(path: string, userMenus: any[]) {
    for (const menu of userMenus) {
      if (menu.type != 2) {
        findPathToMenu(path, menu.children ?? [])
      } else {
        if (menu.url === path) {
          firstMenu = menu
        }
      }
    }
  }

  findPathToMenu(path, userMenus)
  return firstMenu
}

interface IBreadcrumbs {
  name: string
  path?: string
}

/**
 * @param path 当前页面的路径
 * @param userMenus 当前用户全部菜单
 * @param preMenu 匹配当前页面路径时的父级菜单，第一次可以直接给{}空对象
 * @returns 当前页面所匹配的面包屑
 */
export function mapPathToBreadcrumbs(path: string, userMenus: any[], preMenu: any) {
  const breadcrumbs: IBreadcrumbs[] = []

  function findPathToBreadcrumbs(path: string, userMenus: any[], preMenu: any) {
    for (const menu of userMenus) {
      if (menu.type != 2) {
        findPathToBreadcrumbs(path, menu.children ?? [], menu)
      } else {
        if (menu.url === path) {
          // 1. 顶层菜单(需要在动态路由中注册 mapMenusToRoutes)
          breadcrumbs.push({
            name: preMenu.name,
            path: preMenu.url
          })

          // 2. 一级菜单
          breadcrumbs.push({
            name: menu.name,
            path: menu.url
          })
        }
      }
    }
  }

  findPathToBreadcrumbs(path, userMenus, preMenu)
  return breadcrumbs
}

/**
 *
 * @param menuLists 当前树结构的菜单数组
 * @returns 返回当前树结构菜单数组最底层的ids数组集合
 */

export function mapMenus2Ids(menuLists: any) {
  const ids: number[] = []
  function getMenus2Ids(menuLists: any) {
    for (const menu of menuLists) {
      if (menu.children && menu.children.length > 0) {
        getMenus2Ids(menu.children ?? [])
      } else {
        // 只存储最底层id，上层id不需要保存，tree会自动勾选
        ids.push(menu.id)
      }
    }
  }

  getMenus2Ids(menuLists)
  return ids
}

/**
 *
 * @param menuList 用户菜单数据
 * @returns 从menuList tree中获取用户按钮permission权限, tree to array
 */
export function mapMenuList2Permission(menuList: any[]) {
  const permission: string[] = []

  function recurseGetPermission(menuList: any[]) {
    for (const menu of menuList) {
      if (menu.type === 3) {
        permission.push(menu.permission)
      } else {
        recurseGetPermission(menu.children ?? [])
      }
    }
  }
  recurseGetPermission(menuList)
  return permission
}
